package com.cloud.netty.heartbeat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

public class MyServer {

    public static void main(String[] args) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();

        // 创建服务器短的启动对象，配置参数
        ServerBootstrap bootstrap = new ServerBootstrap();

        // 使用链式编程来进行设置
        bootstrap.group(bossGroup,workGroup) // 设置两个线程组
                .channel(NioServerSocketChannel.class) // 使用NioServerSocketChannel作为服务器的通道实现
                .option(ChannelOption.SO_BACKLOG,128) // 设置线程队列得到连接个数
                .childOption(ChannelOption.SO_KEEPALIVE,true) // 设置保持活动连接状态
                .handler(new LoggingHandler(LogLevel.INFO)) // 该handler 对应bossGroup childHandler 对应workGroup
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    // 给pipeline设置处理器
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        // 可以使用一个集合管理socketChannel，再推送消息时，可以将业务加入到各个channel
                        // 对应的NioEventLoop的taskQueue或者scheduleTaskQueue
                        ChannelPipeline pipeline = ch.pipeline();
                        /*
                        * IdleStateHandler 是netty提供的处理空闲状态的处理器
                        * long readerIdleTime 表示多长时间读，就会发送一个心跳检测包检测是否连接
                        * long writerIdleTime 表示多长时间写，就会发送一个心跳检测包检测是否连接
                        * long allIdleTime  表示多长时间读写，就会发送一个心跳检测包检测是否连接
                        *
                        * 当 IdleStateHandler 触发后，就会传递给管道的下一个handler去处理，通过调用(触发)下一个
                        * handler的userEventTriggered,在该方法中去处理IdleStateEvent(读空闲、写空闲、读写空闲)
                        * */
                        pipeline.addLast(new IdleStateHandler(3,5,7, TimeUnit.SECONDS));
                        // 加入一个对空闲检测进一步处理的handler(自定义)
                        pipeline.addLast(null);
                    }
                });
    }
}
